package org.linsoho.xmlupdate;

import java.io.File;
import java.io.FileInputStream;
import java.sql.ResultSet;
import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;

import com.thoughtworks.xstream.core.util.Base64Encoder;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Stage;
import javafx.util.Callback;

public class View extends BorderPane{
    
    private TableView<TableModel> tableView;
    
    public View(Stage primaryStage) {
        this.setPadding(new Insets(5));
        
        VBox btnBox = new VBox();
        btnBox.setSpacing(10);
        btnBox.setPadding(new Insets(2, 0, 2, 5));
        this.setRight(btnBox);
        
        //文件选择器
        FileChooser fileChooser = new FileChooser();
        fileChooser.getExtensionFilters().add(
                new ExtensionFilter("Xml File", "*.xml"));
        
        //模版
        ObservableList<TableModel> data = FXCollections.observableArrayList();
        TableColumn<TableModel, Boolean> selectedCol = new TableColumn<>("选中");
        selectedCol.setMinWidth(50);
        selectedCol.setCellValueFactory(new PropertyValueFactory<>("selected"));
        selectedCol.setCellFactory(new Callback<TableColumn<TableModel, Boolean>, TableCell<TableModel, Boolean>>() {
            
            @Override
            public TableCell<TableModel, Boolean> call(TableColumn<TableModel, Boolean> param) {
                return new CheckBoxTableCell<TableModel, Boolean>();
            }
        });
        
        //文件名称
        TableColumn<TableModel, String> fileNameCol = new TableColumn<>("名称");
        fileNameCol.setMinWidth(180);
        fileNameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
        
        //路径
        TableColumn<TableModel, String> filePathCol = new TableColumn<>("路径");
        filePathCol.setMinWidth(480);
        filePathCol.setCellValueFactory(new PropertyValueFactory<>("path"));
        
        //添加文件
        Button addBtn = new Button("添加");
        addBtn.setMinSize(70, 30);
        addBtn.setOnAction(value -> {
            List<File> files = fileChooser.showOpenMultipleDialog(primaryStage);
            if (files != null) {
                for (File file : files) {
                    addFile(file, data);
                }
            }
        });
        
        //删除文件
        Button delBtn = new Button("删除");
        delBtn.setMinSize(70, 30);
        delBtn.setOnAction(value -> {
            int size = data.size();
            if (size == 0) {
                new Alert(AlertType.WARNING, "请选择文件!").show();
                return;
            }
            
            Optional<ButtonType> result = new Alert(
                    AlertType.CONFIRMATION
                    ,"是否要删除选中的文件?")
                    .showAndWait();
            
            if (result.isPresent() && result.get().equals(ButtonType.OK)) {
                for (int i = size - 1; i >= 0; i--) {
                    TableModel model = data.get(i);
                    if (model.isSelected()) {
                        data.remove(i);
                    }
                }
            }
        });
        
        //上传
        Button uploadBtn = new Button("上传");
        uploadBtn.setMinSize(70, 30);
        uploadBtn.setOnAction(value -> {
            int size = data.size();
            if (size == 0) {
                new Alert(AlertType.WARNING, "请选择文件!").show();
                return;
            }
            Optional<ButtonType> result = new Alert(
                    AlertType.CONFIRMATION,
                    "是否上传已选中的文件!")
                    .showAndWait();
            
            if (result.isPresent() && result.get().equals(ButtonType.OK)) {
                uploadData(data);
            }
        });
        
        btnBox.getChildren().add(addBtn);
        btnBox.getChildren().add(delBtn);
        btnBox.getChildren().add(uploadBtn);
        
        tableView = new TableView<>();
        tableView.setItems(data);
        tableView.setEditable(true);
        tableView.setPrefWidth(700);
        tableView.getColumns().addAll(selectedCol, fileNameCol, filePathCol);
        tableView.setOnDragOver(value -> {
            Dragboard dragboard = value.getDragboard();
            if (dragboard.hasFiles()) {
                List<File> files = dragboard.getFiles();
                boolean isXmlFile = true;
                for (File file : files) {
                    if (!file.getAbsolutePath().endsWith(".xml")) {
                        isXmlFile = false;
                        break;
                    }
                }
                if (isXmlFile) {
                    value.acceptTransferModes(TransferMode.COPY);
                }
            }
        });
        tableView.setOnDragDropped(value -> {
            if (value.isAccepted()) {
                Dragboard dragboard = value.getDragboard();
                List<File> files = dragboard.getFiles();
                for (File file : files) {
                    addFile(file, data);
                }
            }
        });
        
        this.setLeft(tableView);
    }
    
    private void addFile(File file, ObservableList<TableModel> data) {
        if (file != null) {
            TableModel model = new TableModel();
            model.setSelected(true);
            model.setName(file.getName());
            model.setPath(file.getAbsolutePath());
            data.add(model);
        }
    }
    
    private void uploadData(ObservableList<TableModel> data) {
        try {
            boolean success = false;
            for (TableModel model : data) {
                if (model.isSelected()) {
                    String name = verifyName(model.getName());
                    String version = verifyVersion(model.getName());
                    if (version == null) {
                        throw new Exception("文件名出错!");
                    }
                    ResultSet set = ServiceHelper.select(name, version);//检索数据是否存在
                    if (set.next()) {
                        System.out.println("检索成功!");
                        File file = new File(model.getPath());
                        if (file.exists()) {
                            FileInputStream in = new FileInputStream(file);
                            byte[] buffer = new byte[(int) file.length()];
                            in.read(buffer);
                            String base64 = new Base64Encoder().encode(buffer).toString();
                            success = ServiceHelper.update(base64, name, version);
                            in.close();
                        } else {
                            throw new Exception("文件不存在!");
                        }
                    } else {
                        System.out.println("检索失败!");
                        Optional<ButtonType> result = new Alert(
                                AlertType.CONFIRMATION,
                                "模版不存在，是否增加模版!")
                                .showAndWait();
                        
                        if (result.isPresent() && result.get().equals(ButtonType.OK)) {
                            File file = new File(model.getPath());
                            if (file.exists()) {
                                FileInputStream in = new FileInputStream(file);
                                byte[] buffer = new byte[(int) file.length()];
                                in.read(buffer);
                                String base64 = new Base64Encoder().encode(buffer).toString();
                                success = ServiceHelper.insert(base64, name, version);
                                if (success) {
                                    tableView.getItems().clear();
                                } else {
                                    in.close();
                                    throw new Exception("上传失败!");
                                }
                                in.close();
                            } else {
                                throw new Exception("文件不存在!");
                            }
                        }
                    }
                }
            }
            if (success) {
                data.clear();
            }
        } catch (Exception e) {
            Alert alert = new Alert(AlertType.ERROR, e.getMessage());
            alert.show();
        }
    }

    /**
     * 获取票据版本号
     */
    private String verifyVersion(String name) {
        String regex = "\\d+\\.\\d+\\.\\d";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(name);
        while (matcher.find()) {
            return matcher.group();
        }
        return null;
    }

    /**
     * 获取票据的名称
     */
    private String verifyName(String name) {
        int idx = 0;
        int len = 0;
        if (name.contains(Type.DELIVERY)) {
            idx = name.indexOf(Type.DELIVERY);
            len = Type.DELIVERY.length();
            return getMoudleName(name, idx, len, "配送单");
        } else if (name.contains(Type.KITCHEN)) {
            idx = name.indexOf(Type.KITCHEN);
            len = Type.KITCHEN.length();
            return getMoudleName(name, idx, len, "厨房小票");
        } else if (name.contains(Type.LABEL)) {
            idx = name.indexOf(Type.LABEL);
            len = Type.LABEL.length();
            return getMoudleName(name, idx, len, "标签");
        } else if (name.contains(Type.RECEIPT)) {
            idx = name.indexOf(Type.RECEIPT);
            len = Type.RECEIPT.length();
            return getMoudleName(name, idx, len, "收银小票");
        } else if (name.contains(Type.RECHARGE)) {
            idx = name.indexOf(Type.RECHARGE);
            len = Type.RECHARGE.length();
            return getMoudleName(name, idx, len, "储值卡充值");
        }
        return "";
    }

    private String getMoudleName(String name, int idx, int len, String typeNm) {
        String str1 = name.substring(idx + len + 1, idx + len + 2);
        String str2 = name.substring(idx + len + 2, idx + len + 3);
        if (StringUtils.isNumeric(str1) && StringUtils.isNumeric(str2)) {
            return typeNm + str1 + str2;
        } else if (StringUtils.isNumeric(str1)) {
            return typeNm + str1;
        }
        return typeNm;
    }
    
    /**
     * 票据类型
     * @author lxb <linxiaobing@syncpo.com>
     */
    public class Type {
        
        public final static String DELIVERY = "delivery";
        
        public final static String KITCHEN = "kitchen";
        
        public final static String LABEL = "label";
        
        public final static String RECEIPT = "receipt";
        
        public final static String RECHARGE = "recharge";
    }
}
